/*
 * Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.huawei.cloudphoneime;

import java.security.SecureRandom;

public class CaeImeProtocol {
    public static final int IME_MSG_HEADER_LEN = 3;
    public static final int IME_SHOW_KEYBOARD_REQ = 0;
    public static final int IME_HIDE_KEYBOARD_REQ = 1;
    public static final int IME_TEXT_CHANGE_REQ = 2;
    public static final int IME_KEY_EVENT_REQ = 3;
    public static final int IME_HANDSHAKE = 4;
    public static final int IME_HANDSHAKE_ACK = 5;
    public static final int IME_CLIP_BOARD_CONTENT = 6;

    public static class IMEPktHeader {
        private byte mType;
        private int mBodyLen;

        public IMEPktHeader(byte[] data) {
            mType = data[0];
            mBodyLen = (data[1] << 8) | (data[2] & 0xFF);
        }

        public int getType() {
            return mType;
        }

        public int getBodyLen() {
            return mBodyLen;
        }
    }

    public static class IMEShowKeyBoardPkt {
        private byte[] mText;
        public IMEShowKeyBoardPkt(byte[] text) {
            mText = text;
        }

        public byte[] get() {
            byte[] data = null;
            if (mText == null || mText.length == 0) {
                data = new byte[IME_MSG_HEADER_LEN];
                data[0] = IME_SHOW_KEYBOARD_REQ;
                data[1] = 0;
                data[2] = 0;
            } else {
                data = new byte[mText.length + IME_MSG_HEADER_LEN];
                data[0] = IME_SHOW_KEYBOARD_REQ;
                data[1] = (byte) (mText.length >> 8);
                data[2] = (byte) (mText.length & 0xFF);
                System.arraycopy(mText, 0, data, IME_MSG_HEADER_LEN, mText.length);
            }
            return data;
        }

        public int getType() {
            return IME_SHOW_KEYBOARD_REQ;
        }
    }

    public static class IMEHideKeyBoardPkt {
        public byte[] get() {
            byte[] data = new byte[IME_MSG_HEADER_LEN];
            data[0] = IME_HIDE_KEYBOARD_REQ;
            data[1] = 0;
            data[2] = 0;
            return data;
        }

        public int getType() {
            return IME_HIDE_KEYBOARD_REQ;
        }
    }

    public static class IMETextChangePkt {
        private byte[] mText = null;

        public int parseBody(byte[] data, int offset, int bodyLen) {
            mText = new byte[bodyLen];
            System.arraycopy(data, offset, mText, 0, bodyLen);
            return 0;
        }

        public byte[] getText() {
            return mText;
        }

        public int getType() {
            return IME_TEXT_CHANGE_REQ;
        }
    }

    public static class IMEKeyEventPkt {
        private int mKeyCode = 0;

        public int parseBody(byte[] data, int offset) {
            if (offset + 2 != data.length) {
                return -1;
            }
            mKeyCode = (data[offset] << 8) | (data[offset + 1] & 0xFF);
            return 0;
        }

        public int getKeyCode() {
            return mKeyCode;
        }

        public int getType() {
            return IME_KEY_EVENT_REQ;
        }
    }

    public static class IMEHandShakePkt {
        private int code;

        public IMEHandShakePkt() {
            byte[] bytes = new byte[2];
            SecureRandom random = new SecureRandom();
            random.nextBytes(bytes);
            code = ((bytes[1] << 8) | (bytes[0] & 0xFF)) + 1;
        }

        public int getType() {
            return IME_HANDSHAKE;
        }

        public byte[] get() {
            byte[] data = new byte[5];
            data[0] = IME_HANDSHAKE;
            data[1] = 0;
            data[2] = 2;
            data[3] = (byte) ((code & 0xFF00) >> 8);
            data[4] = (byte) (code & 0x00FF);
            return data;
        }

        public int getCode() {
            return code;
        }
    }

    public static class IMEHandShakeAckPkt {
        private int code = 0;

        public int parseBody(byte[] data, int offset) {
            if (offset + 2 != data.length) {
                return -1;
            }
            code = (data[offset] << 8) | (data[offset + 1] & 0xFF);
            return 0;
        }

        public int getCode() {
            return code;
        }

        public int getType() {
            return IME_HANDSHAKE_ACK;
        }
    }

    public static class IMEClipBoardContentPkt {
        private String mContent;

        public IMEClipBoardContentPkt(String content) {
            mContent = content;
        }

        public byte[] get() {
            if (mContent == null || mContent.length() == 0) {
                return null;
            }
            byte[] contentData = mContent.getBytes();
            byte[] data = new byte[IME_MSG_HEADER_LEN + contentData.length];
            data[0] = IME_CLIP_BOARD_CONTENT;
            data[1] = (byte) ((contentData.length & 0xFF00) >> 8);
            data[2] = (byte) ((contentData.length & 0x00FF));
            System.arraycopy(contentData, 0, data, IME_MSG_HEADER_LEN, contentData.length);
            return data;
        }
    }
}
